package com.freewater.springboot.demo.testmanagedtransaction;

import com.freewater.springboot.demo.PackageUtils;
import com.zaxxer.hikari.HikariDataSource;
import org.hibernate.SessionFactory;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
public class AppConfig {

    @Configuration
    @Profile("dev")
    @PropertySource("classpath:/com/freewater/springboot/demo/testmanagedtransaction/dataSource-dev.properties")
    public static class DataSourcePropertiesDev {
    }

    @Configuration
    @Profile("test")
    @PropertySource("classpath:/com/freewater/springboot/demo/testmanagedtransaction/dataSource-test.properties")
    public static class DataSourcePropertiesTest {
    }

    @Bean
    public DataSource dataSource(Environment environment) {
        return DataSourceBuilder.create()
                .type(HikariDataSource.class)
                .url(environment.getRequiredProperty("jdbc.url"))
                .username(environment.getRequiredProperty("jdbc.username"))
                .password(environment.getRequiredProperty("jdbc.password"))
                .driverClassName(environment.getRequiredProperty("jdbc.driverClassName"))
                .build();
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource,
                                                  Environment environment) {
        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        ClassPathResource hbmDirectoryResource = new ClassPathResource(
                PackageUtils.getClassPathFroClass(this.getClass()) + "/hbm");
        factoryBean.setMappingDirectoryLocations(hbmDirectoryResource);
        //
        Properties hibernateProperties = new Properties();
        hibernateProperties.put("hibernate.dialect",
                environment.getRequiredProperty("hibernate.dialect"));
        hibernateProperties.put("hibernate.show_sql",
                environment.getRequiredProperty("hibernate.show_sql"));
        hibernateProperties.put("hibernate.format_sql",
                environment.getRequiredProperty("hibernate.format_sql"));
        hibernateProperties.put("hibernate.hbm2ddl.auto",
                environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
        factoryBean.setHibernateProperties(hibernateProperties);
        return factoryBean;
    }

    @Bean
    public PlatformTransactionManager platformTransactionManager(SessionFactory sessionFactory) {
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(sessionFactory);
        return txManager;
    }

    @Bean
    public UserRepository userRepository(SessionFactory sessionFactory) {
        return new UserRepository(sessionFactory);
    }

}
